/*
 *
 */
package serverClasses;

import clientClasses.Orders;
import commonClasses.commonInterfaces.ProtocolIntf;
import commonClasses.Messages.FinishMsg;
import commonClasses.Messages.ListMsg;
import commonClasses.MagicNumbers;
import commonClasses.Messages.LoginMsg;
import commonClasses.Messages.Msg;
import commonClasses.Messages.QueryMsg;
import commonClasses.Utils;
import commonClasses.commonInterfaces.ClientModelIntf;
import commonClasses.commonInterfaces.HostModelIntf;
import commonClasses.commonInterfaces.ItemIntf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * @author Pozytywny!
 */
public class HostProtocol implements ProtocolIntf {

    private int _port;
    private HostModelIntf _model;
    private DataInputStream _dis;
    private DataOutputStream _dos;

    private class ListeningRunnable implements Runnable {

        private Socket _clientSocket;
        private ProtocolIntf _protocol;
        private String userHash = null;

        public ListeningRunnable(Socket clientSocket, ProtocolIntf protocol) {
            this._clientSocket = clientSocket;
            this._protocol = protocol;

        }

        private void pisz(String s) {
            System.out.println("H <- " + s);
        }

        private void pisz(int s) {
            System.out.println("H <- " + Integer.toString(s));
        }

        public void run() {
            try {


                _dis = new DataInputStream(
                        _clientSocket.getInputStream());

                _dos = new DataOutputStream(
                        _clientSocket.getOutputStream());

                while (_clientSocket.isConnected()) {
                    /*
                     * sprawdza czy aukcje dla przedmiotów w których on bierze
                    udział sie już skończyły jak tak, to wysyła komunikat
                     *
                     */



                    try {
                        Utils.write("sprawdzam");
                        ArrayList<ItemIntf> itemFinishedList = new ArrayList<ItemIntf>();
                        if (userHash != null) {
                            itemFinishedList = _model.getFinishedUserAuctions(userHash);

                            Iterator<ItemIntf> it = itemFinishedList.iterator();

                            while (it.hasNext()) {
                                ItemIntf item = it.next();
                                new FinishMsg(_protocol, item).send();
                                Utils.write("wysłałem zakończene aukcji");
                            }
                        }

                        Utils.write("czekam.");
                        long availiable = 0;
                        try {
                            availiable = _dis.available();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        if (availiable > 0) {
                            long msgID = Msg.receiveMsgId(_dis);
                            Utils.received(msgID);
////////////////////////////////////////////////////////////////////////////////
                            if (msgID == MagicNumbers.QUERY_MSG_NR) {
                                QueryMsg queryMsg = new QueryMsg(_protocol);
                                queryMsg.receive();
                                new QueryMsgService(_protocol, queryMsg.getItemID()).execute();

                            } //////////////////////////////////////////////////////
                            else if (msgID == MagicNumbers.LIST_MSG_NR) {
                                ListMsg listMsg = new ListMsg(_protocol);
                                listMsg.receive();
                                new ListMsgService(_protocol).execute();

                            } //////////////////////////////////////////////////////
                            else if (msgID == MagicNumbers.LOGIN_MSG_NR) {
                                userHash = new LoginMsgService(_protocol, _model).execute();


                            } //////////////////////////////////////////////////////
                            else if (msgID == MagicNumbers.ENTER_MSG_NR) {
                                new EnterAuctionMsgService(_protocol, userHash).execute();


                            } //////////////////////////////////////////////////////
                            else if (msgID == MagicNumbers.NEW_BID_MSG_NR) {
                                new NewBidMsgService(_protocol, userHash).execute();

                            } //////////////////////////////////////////////////////
                            else {
                                pisz("listeningRunnable: " +
                                        "otrzymany mesgID = " + msgID);
                                break;
                            }
                        } else {
                            Thread.sleep(1000);
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                        break;
                    }
                }



            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("lR: koniec");
        }
    }

    public ClientModelIntf getClientModel() {
        throw new UnsupportedOperationException("jestem przecież hostem!");
    }

    public HostModelIntf getHostModel() {
        return _model;
    }

    private class MainThread implements Runnable {

        private ProtocolIntf _protocol;

        public MainThread(ProtocolIntf _protocol) {
            this._protocol = _protocol;
        }

        public void run() {
            try {
                ServerSocket serverSocket = new ServerSocket(_port);

                while (true) {
                    Socket clientSocket = serverSocket.accept();
                    ListeningRunnable lR =
                            new ListeningRunnable(clientSocket, _protocol);
                    (new Thread(lR)).start();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public HostProtocol(int port, HostModelIntf hmf) {
        this._port = port;
        this._model = hmf;
    }

    public void launchHost() {
        MainThread mt = new MainThread(this);
        Thread t = (new Thread(mt));
        t.start();
    }

    public DataInputStream getDIS() {
        return _dis;
    }

    public DataOutputStream getDOS() {
        return _dos;
    }

    public InetAddress getIP() {
        try {
            return InetAddress.getLocalHost();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public int getPort() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Orders getOrders() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Socket getSocket() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public static void main(String[] args) {

        HostModel hostModel = new HostModel("magic");

        HostProtocol hp = new HostProtocol(1337, hostModel);
        hp.launchHost();
    }
}
